home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 8 / QRZ Ham Radio Callsign Database - Volume 8.iso / mac / files / dsp / dspkgctr.z / dspkgctr / gcc / explow.c < prev    next >
C/C++ Source or Header  |  1992-06-08  |  17KB  |  608 lines

  1. /* Subroutines for manipulating rtx's in semantically interesting ways.
  2.    Copyright (C) 1987 Free Software Foundation, Inc.
  3.  
  4.    $Id: explow.c,v 1.3 91/01/14 11:05:14 jeff Exp $
  5.  
  6. This file is part of GNU CC.
  7.  
  8. GNU CC is free software; you can redistribute it and/or modify
  9. it under the terms of the GNU General Public License as published by
  10. the Free Software Foundation; either version 1, or (at your option)
  11. any later version.
  12.  
  13. GNU CC is distributed in the hope that it will be useful,
  14. but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16. GNU General Public License for more details.
  17.  
  18. You should have received a copy of the GNU General Public License
  19. along with GNU CC; see the file COPYING.  If not, write to
  20. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  21.  
  22.  
  23. #include "config.h"
  24. #include "rtl.h"
  25. #include "tree.h"
  26. #include "flags.h"
  27. #include "expr.h"
  28.  
  29. /* Return an rtx for the sum of X and the integer C.  */
  30.  
  31. rtx
  32. plus_constant (x, c)
  33.      register rtx x;
  34.      register int c;
  35. {
  36.   register RTX_CODE code = GET_CODE (x);
  37.   register enum machine_mode mode = GET_MODE (x);
  38.   int all_constant = 0;
  39.  
  40.   if (c == 0)
  41.     return x;
  42.  
  43.   if (code == CONST_INT)
  44.     return gen_rtx (CONST_INT, VOIDmode, (INTVAL (x) + c));
  45.  
  46.   /* If adding to something entirely constant, set a flag
  47.      so that we can add a CONST around the result.  */
  48.   if (code == CONST)
  49.     {
  50.       x = XEXP (x, 0);
  51.       all_constant = 1;
  52.     }
  53.   else if (code == SYMBOL_REF || code == LABEL_REF)
  54.     all_constant = 1;
  55.  
  56.   /* The interesting case is adding the integer to a sum.
  57.      Look for constant term in the sum and combine
  58.      with C.  For an integer constant term, we make a combined
  59.      integer.  For a constant term that is not an explicit integer,
  60.      we cannot really combine, but group them together anyway.  */
  61.  
  62.   if (GET_CODE (x) == PLUS)
  63.     {
  64.       if (GET_CODE (XEXP (x, 0)) == CONST_INT)
  65.     {
  66.       c += INTVAL (XEXP (x, 0));
  67.       x = XEXP (x, 1);
  68.     }
  69.       else if (GET_CODE (XEXP (x, 1)) == CONST_INT)
  70.     {
  71.       c += INTVAL (XEXP (x, 1));
  72.       x = XEXP (x, 0);
  73.     }
  74.       else if (CONSTANT_P (XEXP (x, 0)))
  75.     {
  76.       return gen_rtx (PLUS, mode,
  77.               plus_constant (XEXP (x, 0), c),
  78.               XEXP (x, 1));
  79.     }
  80.       else if (CONSTANT_P (XEXP (x, 1)))
  81.     {
  82.       return gen_rtx (PLUS, mode,
  83.               XEXP (x, 0),
  84.               plus_constant (XEXP (x, 1), c));
  85.     }
  86. #ifdef OLD_INDEXING
  87.       /* Detect adding a constant to an indexed address
  88.      of the form (PLUS (MULT (REG) (CONST)) regs-and-constants).
  89.      Keep the (MULT ...) at the top level of addition so that
  90.      the result is still suitable for indexing and constants
  91.      are combined.  */
  92.       else if (GET_CODE (XEXP (x, 0)) == MULT)
  93.     {
  94.       return gen_rtx (PLUS, mode, XEXP (x, 0),
  95.               plus_constant (XEXP (x, 1), c));
  96.     }
  97.       else if (GET_CODE (XEXP (x, 1)) == MULT)
  98.     {
  99.       return gen_rtx (PLUS, mode, plus_constant (XEXP (x, 0), c),
  100.               XEXP (x, 1));
  101.     }
  102. #endif
  103.     }
  104.   if (c != 0)
  105. #if defined( DSP56000 )
  106.   {
  107.       switch ( GET_MODE ( x ))
  108.       {
  109.       case PSImode:
  110.       if ( POINTER_SIZE < HOST_BITS_PER_INT )
  111.       {
  112.           c &= (( 1 << POINTER_SIZE ) - 1 );
  113.       }
  114.       break;
  115.       
  116.       case SImode:
  117.       if ( BITS_PER_UNIT < HOST_BITS_PER_INT )
  118.       {
  119.           c &= (( 1 << BITS_PER_UNIT ) - 1 );
  120.       }
  121.       break;
  122.       }
  123.       x = gen_rtx (PLUS, mode, x, gen_rtx (CONST_INT, VOIDmode, c));
  124.   }
  125. #else
  126.     x = gen_rtx (PLUS, mode, x, gen_rtx (CONST_INT, VOIDmode, c));
  127. #endif
  128.  
  129.   if (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF)
  130.     return x;
  131.   else if (all_constant)
  132.     return gen_rtx (CONST, mode, x);
  133.   else
  134.     return x;
  135. }
  136.  
  137. /* If X is a sum, return a new sum like X but lacking any constant terms.
  138.    Add all the removed constant terms into *CONSTPTR.
  139.    X itself is not altered.  The result != X if and only if
  140.    it is not isomorphic to X.  */
  141.  
  142. rtx
  143. eliminate_constant_term (x, constptr)
  144.      rtx x;
  145.      int *constptr;
  146. {
  147.   int c;
  148.   register rtx x0, x1;
  149.  
  150.   if (GET_CODE (x) != PLUS)
  151.     return x;
  152.  
  153.   /* First handle constants appearing at this level explicitly.  */
  154.   if (GET_CODE (XEXP (x, 0)) == CONST_INT)
  155.     {
  156.       *constptr += INTVAL (XEXP (x, 0));
  157.       return eliminate_constant_term (XEXP (x, 1), constptr);
  158.     }
  159.  
  160.   if (GET_CODE (XEXP (x, 1)) == CONST_INT)
  161.     {
  162.       *constptr += INTVAL (XEXP (x, 1));
  163.       return eliminate_constant_term (XEXP (x, 0), constptr);
  164.     }
  165.  
  166.   c = 0;
  167.   x0 = eliminate_constant_term (XEXP (x, 0), &c);
  168.   x1 = eliminate_constant_term (XEXP (x, 1), &c);
  169.   if (x1 != XEXP (x, 1) || x0 != XEXP (x, 0))
  170.     {
  171.       *constptr += c;
  172.       return gen_rtx (PLUS, GET_MODE (x), x0, x1);
  173.     }
  174.   return x;
  175. }
  176.  
  177. /* Return an rtx for the size in bytes of the value of EXP.  */
  178.  
  179. rtx
  180. expr_size (exp)
  181.      tree exp;
  182. {
  183.   return expand_expr (size_in_bytes (TREE_TYPE (exp)), 0, SImode, 0);
  184. }
  185.  
  186. /* Not yet really written since C does not need it.  */
  187.  
  188. rtx
  189. lookup_static_chain (context)
  190.      rtx context;
  191. {
  192.   abort ();
  193. }
  194.  
  195. /* Return a copy of X in which all memory references
  196.    and all constants that involve symbol refs
  197.    have been replaced with new temporary registers.
  198.    Also emit code to load the memory locations and constants
  199.    into those registers.
  200.  
  201.    If X contains no such constants or memory references,
  202.    X itself (not a copy) is returned.
  203.  
  204.    X may contain no arithmetic except addition, subtraction and multiplication.
  205.    Values returned by expand_expr with 1 for sum_ok fit this constraint.  */
  206.  
  207. static rtx
  208. break_out_memory_refs (x)
  209.      register rtx x;
  210. {
  211.   if (GET_CODE (x) == MEM || GET_CODE (x) == CONST
  212.       || GET_CODE (x) == SYMBOL_REF)
  213.     {
  214. #if defined( DSP56000 )
  215.       register rtx temp = force_reg (x->mode, x);
  216.       if ( Pmode == x->mode )
  217.       {
  218.       mark_reg_pointer (temp);
  219.       }
  220. #else      
  221.       register rtx temp = force_reg (Pmode, x);
  222.       mark_reg_pointer (temp);
  223. #endif
  224.       x = temp;
  225.     }
  226.   else if (GET_CODE (x) == PLUS || GET_CODE (x) == MINUS
  227.        || GET_CODE (x) == MULT)
  228.     {
  229.       register rtx op0 = break_out_memory_refs (XEXP (x, 0));
  230.       register rtx op1 = break_out_memory_refs (XEXP (x, 1));
  231.       if (op0 != XEXP (x, 0) || op1 != XEXP (x, 1))
  232.     x = gen_rtx (GET_CODE (x), Pmode, op0, op1);
  233.     }
  234.   return x;
  235. }
  236.  
  237. /* Given a memory address or facsimile X, construct a new address,
  238.    currently equivalent, that is stable: future stores won't change it.
  239.  
  240.    X must be composed of constants, register and memory references
  241.    combined with addition, subtraction and multiplication:
  242.    in other words, just what you can get from expand_expr if sum_ok is 1.
  243.  
  244.    Works by making copies of all regs and memory locations used
  245.    by X and combining them the same way X does.
  246.    You could also stabilize the reference to this address
  247.    by copying the address to a register with copy_to_reg;
  248.    but then you wouldn't get indexed addressing in the reference.  */
  249.  
  250. rtx
  251. copy_all_regs (x)
  252.      register rtx x;
  253. {
  254.   if (GET_CODE (x) == REG)
  255.     {
  256.       if (REGNO (x) != FRAME_POINTER_REGNUM)
  257.     x = copy_to_reg (x);
  258.     }
  259.   else if (GET_CODE (x) == MEM)
  260.     x = copy_to_reg (x);
  261.   else if (GET_CODE (x) == PLUS || GET_CODE (x) == MINUS
  262.        || GET_CODE (x) == MULT)
  263.     {
  264.       register rtx op0 = copy_all_regs (XEXP (x, 0));
  265.       register rtx op1 = copy_all_regs (XEXP (x, 1));
  266.       if (op0 != XEXP (x, 0) || op1 != XEXP (x, 1))
  267.     x = gen_rtx (GET_CODE (x), Pmode, op0, op1);
  268.     }
  269.   return x;
  270. }
  271.  
  272. /* Return something equivalent to X but valid as a memory address
  273.    for something of mode MODE.  When X is not itself valid, this
  274.    works by copying X or subexpressions of it into registers.  */
  275.  
  276. rtx
  277. memory_address (mode, x)
  278.      enum machine_mode mode;
  279.      register rtx x;
  280. {
  281.   register rtx oldx;
  282.  
  283.   /* By passing constant addresses thru registers
  284.      we get a chance to cse them.  */
  285.   if (! cse_not_expected && CONSTANT_P (x))
  286.     return force_reg (Pmode, x);
  287.  
  288.   /* Accept a QUEUED that refers to a REG
  289.      even though that isn't a valid address.
  290.      On attempting to put this in an insn we will call protect_from_queue
  291.      which will turn it into a REG, which is valid.  */
  292.   if (GET_CODE (x) == QUEUED
  293.       && GET_CODE (QUEUED_VAR (x)) == REG)
  294.     return x;
  295.  
  296.   /* We get better cse by rejecting indirect addressing at this stage.
  297.      Let the combiner create indirect addresses where appropriate.
  298.      For now, generate the code so that the subexpressions useful to share
  299.      are visible.  But not if cse won't be done!  */
  300.   oldx = x;
  301.   if (! cse_not_expected && GET_CODE (x) != REG)
  302.     x = break_out_memory_refs (x);
  303.  
  304.   /* At this point, any valid address is accepted.  */
  305.   GO_IF_LEGITIMATE_ADDRESS (mode, x, win);
  306.  
  307.   /* If it was valid before but breaking out memory refs invalidated it,
  308.      use it the old way.  */
  309.   if (memory_address_p (mode, oldx))
  310.     goto win2;
  311.  
  312.   /* Perform machine-dependent transformations on X
  313.      in certain cases.  This is not necessary since the code
  314.      below can handle all possible cases, but machine-dependent
  315.      transformations can make better code.  */
  316.   LEGITIMIZE_ADDRESS (x, oldx, mode, win);
  317.  
  318.   /* PLUS and MULT can appear in special ways
  319.      as the result of attempts to make an address usable for indexing.
  320.      Usually they are dealt with by calling force_operand, below.
  321.      But a sum containing constant terms is special
  322.      if removing them makes the sum a valid address:
  323.      then we generate that address in a register
  324.      and index off of it.  We do this because it often makes
  325.      shorter code, and because the addresses thus generated
  326.      in registers often become common subexpressions.  */
  327.   if (GET_CODE (x) == PLUS)
  328.     {
  329.       int constant_term = 0;
  330.       rtx y = eliminate_constant_term (x, &constant_term);
  331.       if (constant_term == 0
  332.       || ! memory_address_p (mode, y))
  333.     return force_operand (x, 0);
  334.  
  335.       y = plus_constant (copy_to_reg (y), constant_term);
  336.       if (! memory_address_p (mode, y))
  337.     return force_operand (x, 0);
  338.       return y;
  339.     }
  340.   if (GET_CODE (x) == MULT || GET_CODE (x) == MINUS)
  341.     return force_operand (x, 0);
  342.  
  343.   /* If we have a register that's an invalid address,
  344.      it must be a hard reg of the wrong class.  Copy it to a pseudo.  */
  345.   if (GET_CODE (x) == REG)
  346.     return copy_to_reg (x);
  347.  
  348.   /* Last resort: copy the value to a register, since
  349.      the register is a valid address.  */
  350.   return force_reg (Pmode, x);
  351.  
  352.  win2:
  353.   x = oldx;
  354.  win:
  355.   if (flag_force_addr && optimize && GET_CODE (x) != REG
  356.       /* Don't copy an addr via a reg if it is one of our stack slots.
  357.      If we did, it would cause invalid REG_EQUIV notes for parms.  */
  358.       && ! (GET_CODE (x) == PLUS
  359.         && (XEXP (x, 0) == frame_pointer_rtx
  360.         || XEXP (x, 0) == arg_pointer_rtx)))
  361.     {
  362.       if (general_operand (x, Pmode))
  363.     return force_reg (Pmode, x);
  364.       else
  365.     return force_operand (x, 0);
  366.     }
  367.   return x;
  368. }
  369.  
  370. /* Like `memory_address' but pretend `flag_force_addr' is 0.  */
  371.  
  372. rtx
  373. memory_address_noforce (mode, x)
  374.      enum machine_mode mode;
  375.      rtx x;
  376. {
  377.   int ambient_force_addr = flag_force_addr;
  378.   rtx val;
  379.  
  380.   flag_force_addr = 0;
  381.   val = memory_address (mode, x);
  382.   flag_force_addr = ambient_force_addr;
  383.   return val;
  384. }
  385.  
  386. /* Return a modified copy of X with its memory address copied
  387.    into a temporary register to protect it from side effects.
  388.    If X is not a MEM, it is returned unchanged (and not copied).
  389.    Perhaps even if it is a MEM, if there is no need to change it.  */
  390.  
  391. rtx
  392. stabilize (x)
  393.      rtx x;
  394. {
  395.   register rtx addr;
  396.   if (GET_CODE (x) != MEM)
  397.     return x;
  398.   addr = XEXP (x, 0);
  399.   if (rtx_unstable_p (addr))
  400.     {
  401.       rtx temp = copy_all_regs (addr);
  402.       rtx mem;
  403.       if (GET_CODE (temp) != REG)
  404.     temp = copy_to_reg (temp);
  405.       mem = gen_rtx (MEM, GET_MODE (x), temp);
  406.       /* Mark returned memref with in_struct
  407.      if it's in an array or structure. */
  408.       if (GET_CODE (addr) == PLUS || MEM_IN_STRUCT_P (x))
  409.     MEM_IN_STRUCT_P (mem) = 1;
  410.       return mem;
  411.     }
  412.   return x;
  413. }
  414.  
  415. /* Copy the value or contents of X to a new temp reg and return that reg.  */
  416.  
  417. rtx
  418. copy_to_reg (x)
  419.      rtx x;
  420. {
  421.   register rtx temp = gen_reg_rtx (GET_MODE (x));
  422.  
  423.   /* If not an operand, must be an address with PLUS and MULT so
  424.      do the computation.  */ 
  425.   if (! general_operand (x, VOIDmode))
  426.     x = force_operand (x, temp);
  427.   
  428.   if (x != temp)
  429.     emit_move_insn (temp, x);
  430.  
  431.   return temp;
  432. }
  433.  
  434. /* Like copy_to_reg but always give the new register mode Pmode
  435.    in case X is a constant.  */
  436.  
  437. rtx
  438. copy_addr_to_reg (x)
  439.      rtx x;
  440. {
  441.   return copy_to_mode_reg (Pmode, x);
  442. }
  443.  
  444. /* Like copy_to_reg but always give the new register mode MODE
  445.    in case X is a constant.  */
  446.  
  447. rtx
  448. copy_to_mode_reg (mode, x)
  449.      enum machine_mode mode;
  450.      rtx x;
  451. {
  452.   register rtx temp = gen_reg_rtx (mode);
  453.   
  454.   /* If not an operand, must be an address with PLUS and MULT so
  455.      do the computation.  */ 
  456.   if (! general_operand (x, VOIDmode))
  457.     x = force_operand (x, temp);
  458.  
  459.   if (GET_MODE (x) != mode && GET_MODE (x) != VOIDmode)
  460.     abort ();
  461.   if (x != temp)
  462.     emit_move_insn (temp, x);
  463.   return temp;
  464. }
  465.  
  466. /* Load X into a register if it is not already one.
  467.    Use mode MODE for the register.
  468.    X should be valid for mode MODE, but it may be a constant which
  469.    is valid for all integer modes; that's why caller must specify MODE.
  470.  
  471.    The caller must not alter the value in the register we return,
  472.    since we mark it as a "constant" register.  */
  473.  
  474. rtx
  475. force_reg (mode, x)
  476.      enum machine_mode mode;
  477.      rtx x;
  478. {
  479.   register rtx temp, insn;
  480.  
  481.   if (GET_CODE (x) == REG)
  482.     return x;
  483.   temp = gen_reg_rtx (mode);
  484.   insn = emit_move_insn (temp, x);
  485.   /* Let optimizers know that TEMP's value never changes
  486.      and that X can be substituted for it.  */
  487.   if (CONSTANT_P (x))
  488.     REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_EQUIV, x, REG_NOTES (insn));
  489.   return temp;
  490. }
  491.  
  492. /* If X is a memory ref, copy its contents to a new temp reg and return
  493.    that reg.  Otherwise, return X.  */
  494.  
  495. rtx
  496. force_not_mem (x)
  497.      rtx x;
  498. {
  499.   register rtx temp;
  500.   if (GET_CODE (x) != MEM)
  501.     return x;
  502.   temp = gen_reg_rtx (GET_MODE (x));
  503.   emit_move_insn (temp, x);
  504.   return temp;
  505. }
  506.  
  507. /* Copy X to TARGET (if it's nonzero and a reg)
  508.    or to a new temp reg and return that reg.  */
  509.  
  510. rtx
  511. copy_to_suggested_reg (x, target)
  512.      rtx x, target;
  513. {
  514.   register rtx temp;
  515.   if (target && GET_CODE (target) == REG)
  516.     temp = target;
  517.   else
  518.     temp = gen_reg_rtx (GET_MODE (x));
  519.   emit_move_insn (temp, x);
  520.   return temp;
  521. }
  522.  
  523. /* Adjust the stack pointer by ADJUST (an rtx for a number of bytes).
  524.    This pops when ADJUST is positive.  ADJUST need not be constant.  */
  525.  
  526. void
  527. adjust_stack (adjust)
  528.      rtx adjust;
  529. {
  530.   adjust = protect_from_queue (adjust, 0);
  531.  
  532. #ifdef STACK_GROWS_DOWNWARD
  533.   emit_insn (gen_add2_insn (stack_pointer_rtx, adjust));
  534. #else
  535.   emit_insn (gen_sub2_insn (stack_pointer_rtx, adjust));
  536. #endif
  537. }
  538.  
  539. /* Adjust the stack pointer by minus ADJUST (an rtx for a number of bytes).
  540.    This pushes when ADJUST is positive.  ADJUST need not be constant.  */
  541.  
  542. void
  543. anti_adjust_stack (adjust)
  544.      rtx adjust;
  545. {
  546.   adjust = protect_from_queue (adjust, 0);
  547.  
  548. #ifdef STACK_GROWS_DOWNWARD
  549.   emit_insn (gen_sub2_insn (stack_pointer_rtx, adjust));
  550. #else
  551.   emit_insn (gen_add2_insn (stack_pointer_rtx, adjust));
  552. #endif
  553. }
  554.  
  555. /* Round the size of a block to be pushed up to the boundary required
  556.    by this machine.  SIZE is the desired size, which need not be constant.  */
  557.  
  558. rtx
  559. round_push (size)
  560.      rtx size;
  561. {
  562. #ifdef STACK_BOUNDARY
  563.   int align = STACK_BOUNDARY / BITS_PER_UNIT;
  564.   if (align == 1)
  565.     return size;
  566.   if (GET_CODE (size) == CONST_INT)
  567.     {
  568.       int new = (INTVAL (size) + align - 1) / align * align;
  569.       if (INTVAL (size) != new)
  570.     size = gen_rtx (CONST_INT, VOIDmode, new);
  571.     }
  572.   else
  573.     {
  574.       size = expand_divmod (0, CEIL_DIV_EXPR, Pmode, size,
  575.                 gen_rtx (CONST_INT, VOIDmode, align),
  576.                 0, 1);
  577.       size = expand_mult (Pmode, size,
  578.               gen_rtx (CONST_INT, VOIDmode, align),
  579.               0, 1);
  580.     }
  581. #endif /* STACK_BOUNDARY */
  582.   return size;
  583. }
  584.  
  585. /* Return an rtx representing the register or memory location
  586.    in which a scalar value of data type VALTYPE
  587.    was returned by a function call to function FUNC.
  588.    FUNC is a FUNCTION_DECL node if the precise function is known,
  589.    otherwise 0.  */
  590.  
  591. rtx
  592. hard_function_value (valtype, func)
  593.      tree valtype;
  594.      tree func;
  595. {
  596.   return FUNCTION_VALUE (valtype, func);
  597. }
  598.  
  599. /* Return an rtx representing the register or memory location
  600.    in which a scalar value of mode MODE was returned by a library call.  */
  601.  
  602. rtx
  603. hard_libcall_value (mode)
  604.      enum machine_mode mode;
  605. {
  606.   return LIBCALL_VALUE (mode);
  607. }
  608.